package zhongbo.java.air.monitor.Service.impl;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.Polygon;
import org.springframework.stereotype.Service;
import zhongbo.java.air.monitor.Service.IJtsService;
import zhongbo.java.air.monitor.model.dto.PointDto;
import zhongbo.java.air.monitor.util.JtsUtil;

import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class JtsServiceImpl implements IJtsService {

    /*
    多边形至少4个点数据, 第一个数据和最后一个数据一致, 表示点位闭合
    比如三角形最少3个点, 再加一个结束闭合点, 一共需要4个点;
         首点    一点  二点   末尾点(与首点重合)
    如: [[0,0],[0,1],[1,1],[0,0]]
    多边形示例:
    [
        {"longitude":115.95,"latitude":40.45},
        {"longitude":115.95,"latitude":39.48},
        {"longitude":117.2,"latitude":39.41},
        {"longitude":117.49,"latitude":40.41},
        {"longitude":115.95,"latitude":40.45}
    ]
     */
    @Override
    public List<PointDto> parseAlertZoneVertices(String vertices) {
        // Coordinate coordinate = new Coordinate()
        JSONArray jsonArray = JSONUtil.parseArray(vertices);
        List<PointDto> pointList = jsonArray.toList(PointDto.class);
        if (!validAreaPointList(pointList)) {
            return null;
        }
        return pointList;
    }

    private boolean validAreaPointList(List<PointDto> pointList) {
        if (pointList == null) {
            log.error("校验失败! 多边形点位数据为 null");
            return false;
        }
        if (pointList.size() < 4) {
            log.error("校验失败! 多边形点位数据数量错误: {}", pointList);
            return false;
        }
        PointDto firstPoint = pointList.get(0);
        PointDto lastPoint = pointList.get(pointList.size() - 1);
        if (!firstPoint.equals(lastPoint)) {
            log.error("校验失败! 多边形点位数据数量错误: {}", pointList);
            return false;
        }
        return true;
    }

    @Override
    public boolean isInAlertZone(List<PointDto> pointList, Double longitude, Double latitude) {
        if (!validAreaPointList(pointList)) {
            throw new RuntimeException("无效的区域多边形");
        }
        Polygon polygon = convertToPolygon(pointList);
        Point point = JtsUtil.createPoint(longitude, latitude);
        return JtsUtil.isPointInPolygon(point, polygon);
    }

    /**
     * 转换为多边形对象
     *
     * @param pointList 多边形数据列表
     * @return Polygon
     */
    private Polygon convertToPolygon(List<PointDto> pointList) {
        List<Coordinate> collect = pointList.stream().map(e -> {
            Double longitude = e.getLongitude();
            Double latitude = e.getLatitude();
            return JtsUtil.createCoordinate(longitude, latitude);
        }).collect(Collectors.toList());

        Coordinate[] coordinates = ArrayUtil.toArray(collect, Coordinate.class);

        return JtsUtil.createPolygon(coordinates);
    }
}
